import sys
import os
import stat
import logging
import yaml
import sqlite3
import re
import Image
from time import localtime,strftime
from lxml import etree as et

from sqlite3_dbi import dbi
from gallery_utils import relpath

class web_photo_gallery:
    def __init__(self, config):
        fd = open(config, 'r')
        self.conf = yaml.load(fd)
        fd.close()

        self.title = self.conf['title']
        self.gallery_root = self.conf['gallery_root']
        self.backup = self.conf['backup_root']
        self.output_root = self.conf['output_root']
        self.normal_size = self.conf['normal_size']
        self.thumb_size = self.conf['thumb_size']
        self.debug = self.conf['debug'].lower()
        db_name = self.conf['db_name']

        self.log = logging.getLogger(self.__class__.__name__ + '.' + self.title)

        self.conn = sqlite3.connect(db_name)
        self.cur = self.conn.cursor()
        self.cur2 = self.conn.cursor()
        self.db = dbi(self.cur)


        gallery_tb_def = (('pkey','primary_key'),
                          ('file','text'), # path to file (relative to gallery_root in conf)
                          ('normal','text'), # the normal file path (relative to output_root in conf)
                          ('thumb','text'), # the thumbnail file path (relative to output_root in conf)
                          ('name','text'),
                          ('create_date', 'integer'),
                          ('size', 'integer'),
                          ('normal_size', 'integer'),
                          ('thumb_size', 'integer'),
                          ('comment','text'),
                          ('display','text'),
                          ('backup','text'),
                          ('exist','text'),
                          ('album','text'), # album name
                         )
        self.gallery_tn = 'gallery'
        self.db.create_table(self.gallery_tn, gallery_tb_def, False)
        self.cur.execute('create index if not exists album on %s (album)' % self.gallery_tn)

        self.conn.commit()

    def get_relative_path(self, root):
        'this function is better named to *strip root path*'
        plist = root.split('/')
        return '/'.join(plist[1:])

    def process_img(self, root, fn, ignore_list = []):
        fnpath = os.path.join(root,fn)
        if not fnpath in ignore_list:
            stat_result = os.stat(fnpath)
            create_time = stat_result[stat.ST_MTIME]
            photo_size = stat_result[stat.ST_SIZE]
            im = Image.open(fnpath)
            rpath = os.path.join(self.output_root, self.get_relative_path(root))
            im_thumb = im.copy()
            im.thumbnail(self.normal_size, Image.ANTIALIAS)
            normal = im
            normal_path = os.path.join(rpath , 'normal')
            if not os.path.isdir(normal_path):
                os.makedirs(normal_path)
            normal_file = os.path.join(normal_path, fn)
            normal.save(normal_file, 'JPEG')
            normal_size = os.stat(normal_file)[stat.ST_SIZE]
            im_thumb.thumbnail(self.thumb_size, Image.ANTIALIAS)
            thumb = im_thumb
            thumb_path = os.path.join(rpath , 'thumb')
            if not os.path.isdir(thumb_path):
                os.makedirs(thumb_path)
            thumb_file = os.path.join(thumb_path, fn)
            thumb.save(thumb_file, 'JPEG')
            thumb_size = os.stat(thumb_file)[stat.ST_SIZE]

            # update database
            vd = {'file': relpath(fnpath, self.gallery_root),
                  'normal': relpath(normal_file, self.output_root),
                  'thumb': relpath(thumb_file, self.output_root),
                  'name': fn,
                  'create_date': create_time,
                  'size': photo_size,
                  'normal_size': normal_size,
                  'thumb_size': thumb_size,
                  'Comment': 'No Comment',
                  'display': 'Y',
                  'backup': 'Y',
                  'exist': 'Y',
                  'album': os.path.basename(root),
                 }
            self.db.insert(self.gallery_tn, vd, replace=True)
        else:
            self.log.debug('ignoring file: %s' % fnpath)

    def get_ignore_list(self):
        sql = 'select file,exist from %s where exist = "Y"' % self.gallery_tn
        self.cur.execute(sql)
        ignore_list = [os.path.join(self.gallery_root, fp).encode('utf-8') for fp,exist in self.cur.fetchall()]
        for item in ignore_list:
            self.log.debug(item)
        return ignore_list

    def build_index(self):
        ignore_list = self.get_ignore_list()
        p = re.compile('.*\.jpg$',re.I) # matches abc.jpg file
        for root,dirs,files in os.walk(self.gallery_root):
            for fn in files:
                if p.search(fn):
                    self.process_img(root, fn, ignore_list)
            self.conn.commit()

    def create_xml(self):
        ''' Using lxml.etree as et
        '''
        root = et.Element("gallery")
        # first, get all albums
        sql = "select album from %s group by album;" % self.gallery_tn
        self.cur.execute(sql)
        album_id = 0
        for album in self.cur.fetchall():
            album_name = album[0]
            sql = "select * from %s where album='%s'order by create_date;" % (self.gallery_tn, album_name)
            album = et.Element("album")
            album.attrib['name'] = album_name
            album.attrib['id'] = str(album_id)
            album_id += 1
            self.cur2.execute(sql)
            img_id = 0
            for img in self.cur2.fetchall():
                image = et.Element("image")
                image.attrib['id'] = str(img_id)
                img_id += 1
                name = et.Element("name"); name.text = img[4]
                image.append(name)
                path_o = et.Element("path_o"); path_o.text = os.path.join(self.gallery_root,img[1])
                image.append(path_o)
                path_n = et.Element("path_n"); path_n.text = os.path.join(self.output_root,img[2])
                image.append(path_n)
                path_t = et.Element("path_t"); path_t.text = os.path.join(self.output_root,img[3])
                image.append(path_t)
                size = et.Element("size_o"); size.text = str(img[6])
                image.append(size)
                size = et.Element("size_n"); size.text = str(img[7])
                image.append(size)
                size = et.Element("size_t"); size.text = str(img[8])
                image.append(size)
                date = et.Element("date"); date.text = strftime('%Y-%m-%d %H:%M:%S', localtime(img[5]))
                image.append(date)
                comment = et.Element("comment"); comment.text = img[9]
                image.append(comment)
                display = et.Element("display"); display.text = img[10]
                image.append(display)
                backup = et.Element("backup"); backup.text = img[11]
                image.append(backup)
                exist = et.Element("exist"); exist.text = img[12]
                image.append(exist)
                album.append(image)
            root.append(album)
        return root
#       return et.tostring(root, encoding='UTF-8', xml_declaration=True, pretty_print=True, method="xml")

if __name__ == '__main__':
    debug_level = {'enable':logging.DEBUG, 'disable':logging.INFO}
    x = web_photo_gallery('gallery.conf')
    logging.basicConfig(level=debug_level[x.debug])
    x.build_index()
    root = x.create_xml()
#   xsl_doc = et.parse('test.xsl')
#   transform = et.XSLT(xsl_doc)
#   result = transform(root)
    fd = open('test.xml','w')
    fd.write(et.tostring(root, encoding='UTF-8', xml_declaration=True, pretty_print=True, method="xml"))
    fd.close()
    sys.stderr.write("Job Done!\n")
